package heap

import (
	. "jvm/typedef"
	"unicode/utf16"
)

var internedStrings = map[string]*Object{}

// *******************************************************
// go string 转java String
func JString(loader *ClassLoader, goStr string) *Object {
	if internedStr, ok := internedStrings[goStr]; ok {
		return internedStr
	}
	chars := stringToUtf16(goStr)
	jChars := &Object{
		class: loader.LoadClass("[C"),
		data:  chars,
	}
	jStr := loader.LoadClass("java/lang/String").NewObject()
	jStr.SetRefVar("value", "[C", jChars)
	internedStrings[goStr] = jStr
	return jStr
}
func stringToUtf16(s string) []U2 {
	runes := []rune(s)
	arr := utf16.Encode(runes)
	chars := make([]U2, len(arr))
	for i := 0; i < len(arr); i++ {
		chars[i] = U2(arr[i])
	}
	return chars
}

// *******************************************************
// java String转go string
func GoString(jStr *Object) string {
	jChars := jStr.GetRefVar("value", "[C")
	arr := jChars.data.([]U2)
	chars := make([]uint16, len(arr))
	for i := 0; i < len(arr); i++ {
		chars[i] = uint16(arr[i])
	}
	return string(utf16.Decode(chars))
}

// 若字符串池中已有该字符串，返回已有的字符串，
// 否则将该字符串入池，并返回
func InternString(jStr *Object) *Object {
	goStr := GoString(jStr)
	if ref, ok := internedStrings[goStr]; ok {
		return ref
	}
	internedStrings[goStr] = jStr
	return jStr
}
